let log4js = require('log4js');
 log4js.configure({
    appenders: {fileout: { type: "file", filename: "./logs/event.log" },consoleout: { type: "console" }},
    categories: {default: { appenders: ["fileout","consoleout"], level: "info" }}
})
let log = log4js.getLogger("event");
log.level = "info"; // default level is OFF - which means no logs at all.


const ethers = require("ethers");
const dayjs = require("dayjs");
const Big = require('big.js');
const wallet = require("./common/wallet");

const db = require("./common/mysql");
const redis = require("./common/redis").redis;
const config = require("./common/config").config;


// WebSocket
const provider = new ethers.JsonRpcProvider(config.rpcProviderUrl);
const contractAddress = config.contractAddress;
const contractABI = require("./common/abi.json");
const contract = new ethers.Contract(contractAddress, contractABI, provider);

// 获取 Transfer 事件
const getEvents=async () =>{
    try {
        // const events = await contract.queryFilter('Buy', 45441385,'latest');
        const latestBlock = await provider.getBlockNumber();
        const fromBlock = latestBlock - 10000; 

        log.debug('bsc query buy event ...');
        const events = await contract.queryFilter('Buy', fromBlock,latestBlock);
        log.debug('retrieved events:', events);  // 打印返回的事件
        if (events.length === 0) {
            log.info('No events found.');
            return;
        }
        log.info("found events :",events.length);
        events.forEach(event => {
            // console.log('Event Name:', event.fragment.name);
            // console.log('Event args.address:', event.args[0]);
            // console.log('Event args.buyValue:', event.args[1]);
            // console.log('Event args.buyTime:', event.args[2]);
            // console.log('Event args.orderIndex:', event.args[3]);
            const data={
                transactionHash:event.transactionHash,
                blockNumber:event.blockNumber,
                buyer:event.args[0],
                buyValue:event.args[1],
                buyTime:event.args[2],
                orderIndex:event.args[3]
            };
            getByTransactionHash(data.transactionHash)
            .then((results) => {
                if(results.length>0){
                    return;
                }
                saveBuy(data);
            }).catch((err) => {
                log.error("getByTransactionHash err:",err);
            });
        });
    } catch (error) {
        console.error('Error fetching events:', error);
    }
}

const getByTransactionHash = (transactionHash) => {
    return new Promise((resolve, reject) => {
        let sql = `select * from app_buy where transaction_hash='${transactionHash}'`
        log.debug("getByTransactionHash: ",sql);
        db.query(sql, (error, results,fields) => {
            if (error) {
                reject(error);
            } else {
                resolve(results);
            }
        })
   }
)}



const saveBuy= async (data)=>{
    parse(data);
    log.info("Save buy: ",data);

    const state=await wallet.includes(data.buyer)?0:1;
    log.info(`${data.buyer} state: ${state}`);
    
    const sql = "INSERT INTO `uzi`.`app_buy` (state,transaction_hash,block_number,`buyer`, `buy_value`, `buy_time`, `order_index`,  `reward_count`, `reward_amount`, `reward_time`, `reward_next_time`, `market_count`, `market_amount`, `market_time`, `market_next_time`, `create_time`, `update_time`) VALUES "
    +`(${state},'${data.transactionHash}','${data.blockNumber}','${data.buyer}', ${data.buyValue}, '${data.buyTime}', ${data.orderIndex}, ${data.rewardCount},${data.rewardAmount},null,'${data.rewardNextTime}',${data.marketCount},${data.marketAmount},null,'${data.marketNextTime}', now(), now());`;

    if(!data.buyer){
        return;
    }

    db.query(sql, (error, results) => {
        if(error){
            // 创建失败
            log.error(`save buy error: ${data.transactionHash} ${error.sqlMessage} \n ${sql}`);
        } else {
            // 创建成功
            log.info(`save buy successfully ${data.transactionHash}`)
        }
    })
}

const parse=(data) => {
    const buyTime=new Big(data.buyTime).mul(1000).toNumber()
    const buyTimeFmt=dayjs(buyTime).format('YYYY-MM-DD HH:mm:ss');
    data.buyTime=buyTimeFmt;
    
    const buyValueFmt = ethers.formatUnits(data.buyValue, 18); 
    data.buyValue=buyValueFmt;

    data.rewardCount=0;
    data.rewardAmount=0;
    data.rewardNextTime=buyTimeFmt;
    
    data.marketCount=0;
    data.marketAmount=0;
    data.marketNextTime=dayjs(buyTimeFmt).add(config.marketDelay,'minute').format('YYYY-MM-DD HH:mm:ss');
}


const pubBuy=(data)=>{
    const channel = 'event-buy';
    log.info(`publish channel: ${channel} message: ${data}`);
    redis.publish(channel, JSON.stringify(data));
}

function bigIntReplacer(key, value) {
    if (typeof value === 'bigint') {
      return value.toString(); // Convert BigInt to string
    }
    return value; // Return other values unchanged
  }


// test
// owner: 0x81828932845D4B38C5C5af2e856e8e34c54d1f1D
// msgValue: 1500000000000000
// timestamp: 1735844015
// orderIndex: 3
const data={
    buyer:'0x81828932845D4B38C5C5af2e856e8e34c54d1f1D',
    buyValue:'1500000000000000',
    buyTime:1735844015,
    orderIndex:3
};


// saveBuy(data);
// pubBuy(data);

const run=()=>{
    setInterval(()=>{
        log.info("event task interval");
        getEvents();
    },1*1000);
}

run();

module.exports = {
	run
}

